home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr05 / xnot12a.zip / W3KEY.C < prev    next >
C/C++ Source or Header  |  1993-06-16  |  13KB  |  607 lines

  1. #ifdef MSW
  2.  
  3. /* Keyboard stuff; in reality, this code performs a lot of tedious
  4. * mappings of Windows keycodes to something notgnu emacs understands.
  5. * In some cases, hard-wired mappings are done - ie a key is hit and
  6. * an entire function name is pushed into the input stream. (For more
  7. * info on that funcky mechanism, see extend.c. I created something
  8. * much like Meta-X <name cmd> for parsing input-to-function mapping,
  9. * the difference being there is no echo, it handles 'interruptions'
  10. * and is disabled during macro recording).
  11. *
  12. * You'll note also that the input queue is initialized, and managed here
  13. * as well as something called the putback queue. This is to handle
  14. * interruptions during processing of modeline stuff; the editor base
  15. * code does not want to deal with the concept of something else being
  16. * able to happen during a prompt, and this ughly hack got around that
  17. * problem and a number of others too. Ugh.
  18. *
  19. * The worst stuff is the odd switch statements where Microsoft decided
  20. * that most Fkeys were one kind of message, but some others weren't.
  21. * That and the (to me) quite strange way some keys generate multiple
  22. * messages for each press; you'll see comments to that effect.
  23. */
  24.   
  25. #include "jam.h"
  26. #include "stdlib.h"
  27. #include "def.h"
  28. #include "keyname.h"
  29. #include "ttydef.h"
  30. #include "chrdef.h"
  31.   
  32. #define MAXCHARS 256
  33. static KCHAR *kbdinput = 0;
  34. static KCHAR *putback_kbdinput = 0;
  35. static int kbdcount = 0;
  36. static int putback_kbdcount = 0;
  37.  
  38. static BOOL s_IgnoreWM_CHAR = FALSE;  /* WM_KEYDOWN/WM_SYSKEYDOWN may generate
  39.                                        * a following WM_CHAR to ignore
  40.                                        */
  41. static BOOL mapFkey(WPARAM *wKey, BOOL bShifted, BOOL bCtrled, BOOL bAlted);
  42. static BOOL mapKPkey(WPARAM *wKey);
  43.  
  44. /* Alloc the internal event queues
  45. */
  46. void InitInput(void)
  47. {
  48.  if (!(kbdinput = (KCHAR *)calloc(MAXCHARS, sizeof(KCHAR))))
  49.    WindowMessage("Unable to init kbdinput!", TRUE);
  50.  if (!(putback_kbdinput = (KCHAR *)calloc(MAXCHARS, sizeof(KCHAR))))
  51.    WindowMessage("Unable to init putback_kbdinput!", TRUE);
  52. }
  53.  
  54. /* Putback kchar to to input queue; called to unwind something
  55.  * for replay.
  56.  */
  57. void PutbackKchar(KCHAR c)
  58. {
  59.   if (putback_kbdcount < MAXCHARS)
  60.     {
  61.       putback_kbdinput[putback_kbdcount] = c;
  62.       putback_kbdcount++;
  63.     }
  64. }
  65.  
  66. /* If putback'ed events, push to normal input stream now for replay.
  67. */
  68. void CheckForPutback(void)
  69. {
  70.   int i, j;
  71.  
  72.   /* if not enough room, die
  73.   */
  74.   if ((MAXCHARS - kbdcount) < putback_kbdcount)
  75.     putback_kbdcount = 0;
  76.   else
  77.     for (j = putback_kbdcount, i = 0; i < j; i++)
  78.        {
  79.        AddKchar(putback_kbdinput[i]);
  80.        putback_kbdcount--;
  81.        }
  82. }
  83.  
  84. /* Push normal string to input buf; used all over
  85. * to push function names and parameters into the input
  86. * stream just as if the user had typed them.
  87. */
  88. void AddString(char *s)
  89. {
  90.   while (s && *s)
  91.     AddKchar((KCHAR)*s++);
  92. }
  93.  
  94. /* Add kchar to internal queue of keypresses; like above,
  95. * seems like the user just typed them in...
  96. */
  97. void AddKchar(KCHAR c)
  98. {
  99.   if (kbdcount < MAXCHARS)
  100.     {
  101.       kbdinput[kbdcount] = c;
  102.       kbdcount++;
  103.     }
  104.   else
  105.     MessageBeep((UINT)-1);    /* no more space, sigh */
  106. }
  107.  
  108. /* Return first inqueued char from event into
  109.  * pkchar (if NON_NULL) and return status.
  110.  */
  111. BOOL WindowReturnKCHAR(KCHAR *pkchar)
  112. {
  113.   register int i;
  114.   BOOL result = FALSE;
  115.   
  116.   /* If something, remove from queue head 
  117.    * and push the queue down
  118.    * (I know, should use head/tail pointers vs this copy down 
  119.    *  thing, but ...)
  120.    */
  121.   if (kbdcount > 0)
  122.     {
  123.       result = TRUE;
  124.       if (pkchar)
  125.     {
  126.       *pkchar = kbdinput[0];
  127.       kbdcount--;
  128.       for (i = 0; i < kbdcount; i++)
  129.         kbdinput[i] = kbdinput[i+1];
  130.     }
  131.     }
  132.   return(result);
  133. }
  134.  
  135. /* Map windows event + keycode to kchar; this gets
  136.  * pretty hairy in spots.
  137.  */
  138. BOOL WindowMapKey(UINT msg, WPARAM wKey, LPARAM lParam)
  139. {
  140.   BOOL ignore;
  141.   BOOL bShifted = (GetKeyState(VK_SHIFT) < 0)? 1 : 0;
  142.   BOOL bCtrled = (GetKeyState(VK_CONTROL) < 0)? 1 : 0;
  143.   BOOL bAlted = (GetKeyState(VK_MENU) < 0)? 1 : 0;
  144.  
  145.   /* Events to ignore - we see them in multiple ways. It
  146.    * makes sense to someone.
  147.    */ 
  148.   if (wKey == VK_SHIFT   || wKey == VK_CONTROL || 
  149.       wKey == VK_CAPITAL || wKey == VK_MENU)
  150.     return (FALSE);
  151.   
  152.   /* Pre-processed stuff, with simple mapping
  153.    */
  154.   if (msg == WM_CHAR)        /* Windows has created something useful */
  155.     {
  156.       ignore = s_IgnoreWM_CHAR;
  157.       s_IgnoreWM_CHAR = FALSE;    /* reset */
  158.  
  159.       /* A prior event triggered this wm_char, so it's
  160.        * not useful.
  161.        */
  162.       if (ignore)
  163.         return(FALSE);
  164.  
  165.       switch (wKey)
  166.     {
  167.       case ' ':            
  168.           if (bCtrled)        /* a hard-wired key, cntrl-space */
  169.             {
  170.               ExtendedFunction(function_name(setmark));
  171.               return (TRUE);
  172.             }
  173.           else
  174.             break;
  175.       case CCHR('H'):
  176.       if (!bCtrled)    /* must be backspace key */
  177.         return(FALSE); /* backspace key sends message w/o cntrl key */
  178.       case CCHR('I'):      /* tab is hardwired to C-align function */
  179.           if (bShifted)    /* but cntrl or shift tab is the real thing */
  180.             {
  181.               ExtendedFunction(function_name(hardtab));
  182.               return(TRUE);
  183.             }
  184.     }
  185.       AddKchar((KCHAR)wKey);
  186.       return(TRUE);
  187.     }
  188.   
  189.   /* Keys otherwise eaten
  190.    */
  191.   else if (msg == WM_KEYDOWN)
  192.     {
  193.       switch(wKey)
  194.     {         
  195.       case VK_TAB:      /* tab is hardwired to C-align function */
  196.           if (bCtrled)
  197.             {
  198.               ExtendedFunction(function_name(hardtab));
  199.               return(TRUE);
  200.             } 
  201.           return(FALSE);
  202.  
  203.      case VK_BACK:
  204.       wKey = 0x7f;   /* ttyio mapped it this way too, ick ! */
  205.       break;
  206.  
  207.     case VK_DELETE:
  208.       if (bCtrled)    /* Talk about your hardwired functions! */
  209.         {             /* cntrl-delete wipes a line from any position */
  210.           ExtendedFunction(function_name(gotobol));
  211.           ExtendedFunction(function_name(killline));
  212.           ExtendedFunction(function_name(killline));
  213.           return(TRUE);
  214.         }
  215.       else if (bShifted)  /* This is hardwired too */
  216.         {
  217.           ExtendedFunction(function_name(delbword));
  218.           return(TRUE);
  219.         }
  220.       else
  221.         wKey = KDELETE;
  222.       break;
  223.       
  224.     case VK_INSERT:
  225.       wKey = KINSERT;
  226.       break;
  227.       
  228.     case VK_HOME:
  229.           if (bCtrled)
  230.         wKey = KCHOME;
  231.           else
  232.         wKey = KHOME;
  233.       break;
  234.       
  235.     case VK_END:
  236.           if (bCtrled)
  237.         wKey = KCEND;
  238.           else
  239.         wKey = KEND;
  240.       break;
  241.       
  242.     case VK_RIGHT:
  243.       if (bCtrled)
  244.         wKey = KCRIGHT;
  245.       else
  246.         wKey = KRIGHT;
  247.       break;
  248.       
  249.     case VK_LEFT:
  250.       if (bCtrled)
  251.         wKey = KCLEFT;
  252.       else
  253.         wKey = KLEFT;
  254.       break;
  255.       
  256.     case VK_DOWN:
  257.       if (bCtrled)
  258.             {
  259.             if (bAlted)    /* Down key hardwired for cntrl/alt mix */
  260.               ExtendedFunction(function_name(nextwind));
  261.             else
  262.               ExtendedFunction(function_name(forw1page));
  263.             return (TRUE);
  264.             }
  265.       else 
  266.         wKey = KDOWN;
  267.       break;
  268.       
  269.     case VK_UP:
  270.       if (bCtrled)
  271.             {
  272.               if (bAlted) /* Up key hardwired for cntrl/alt mix */
  273.                 ExtendedFunction(function_name(prevwind));
  274.               else
  275.                 ExtendedFunction(function_name(back1page));
  276.               return (TRUE);
  277.             }
  278.       else
  279.         wKey = KUP;
  280.       break;
  281.       
  282.     case VK_PRIOR:
  283.       if (bCtrled)
  284.         wKey = KCPGUP;
  285.       else
  286.         wKey = KPGUP;
  287.       break;
  288.       
  289.     case VK_NEXT:
  290.       if (bCtrled)
  291.         wKey = KCPGDN;
  292.       else
  293.         wKey = KPGDN;
  294.       break;
  295.  
  296.     case VK_F1:
  297.     case VK_F2:
  298.     case VK_F3:
  299.     case VK_F4:
  300.     case VK_F5:
  301.     case VK_F6:
  302.     case VK_F7:
  303.     case VK_F8:
  304.     case VK_F9:
  305.     case VK_F10:    /* only seen in WM_SYSKEYDOWN, why? */
  306.     case VK_F11:
  307.     case VK_F12:
  308.           if (!mapFkey(&wKey, bShifted, bCtrled, bAlted))
  309.             return (FALSE);
  310.           break;
  311.  
  312.         /* keypad keys
  313.          */
  314.         case VK_NUMPAD0:
  315.         case VK_NUMPAD1:
  316.         case VK_NUMPAD2:
  317.         case VK_NUMPAD3:
  318.         case VK_NUMPAD4:
  319.         case VK_NUMPAD5:
  320.         case VK_NUMPAD6:
  321.         case VK_NUMPAD7:
  322.         case VK_NUMPAD8:
  323.         case VK_NUMPAD9:
  324.         case VK_ADD:
  325.         case VK_MULTIPLY:
  326.         case VK_SUBTRACT:
  327.         case VK_DECIMAL:
  328.         case VK_DIVIDE:
  329.         case VK_EXECUTE:
  330.         case VK_NUMLOCK:
  331.           if (!mapKPkey(&wKey))
  332.             return (FALSE);
  333.           break;
  334.  
  335.     /* Alphanumerics which don't generate WM_CHAR msgs
  336.      * when the cntrl key is down (beats me why!?)
  337.      */
  338.     case 'T':
  339.     case 'P':
  340.     case 'R':
  341.     case 'Q':
  342.       if (bCtrled)
  343.         {
  344.           wKey = CCHR(wKey);  /* really is cntrl-* this time */
  345.           break;
  346.         }
  347.       /* FALLTHRU */
  348.       
  349.       /* NOTE if not known char, OR possible duplicate,
  350.        * do not process
  351.        */
  352.     case VK_RETURN:
  353.     default:
  354.       return(FALSE);
  355.     }
  356.       AddKchar((KCHAR)wKey);
  357.       return(TRUE);
  358.     }
  359.   
  360.   /* Why on why is only F10 a WM_SYSKEYDOWN??
  361.   */
  362.   else if (msg == WM_SYSKEYDOWN)
  363.     {
  364.       switch(wKey)
  365.     {
  366.     case VK_F1:
  367.     case VK_F2:
  368.     case VK_F3:
  369.     case VK_F4:
  370.     case VK_F5:
  371.     case VK_F6:
  372.     case VK_F7:
  373.     case VK_F8:
  374.     case VK_F9:
  375.     case VK_F10:
  376.     case VK_F11:
  377.     case VK_F12:
  378.           if (!mapFkey(&wKey, bShifted, bCtrled, bAlted))
  379.             return (FALSE);
  380.       break;
  381.         default:
  382.           return (FALSE);      
  383.         }
  384.       AddKchar((KCHAR)wKey);
  385.       return(TRUE);
  386.     }
  387.  
  388.   /* Keys with meta-bit set
  389.    */
  390.   else if (msg == WM_SYSCHAR)
  391.     {
  392.       switch(wKey)
  393.     {
  394.     default:
  395.       wKey |= METABIT; 
  396.       break;
  397.     }
  398.       AddKchar((KCHAR)wKey);
  399.       return(TRUE);
  400.     }
  401.   
  402.   /* Unsupported key/message combination
  403.    */
  404.   return (FALSE);
  405. }
  406. /* Function key mapping - broken out for ease of
  407. * mapping.
  408. */
  409. static BOOL mapFkey(WPARAM *pwKey, BOOL bShifted, BOOL bCtrled, BOOL bAlted)
  410. {
  411.   WPARAM wKey = *pwKey;
  412.   BOOL mapped = TRUE;
  413.  
  414.   switch(wKey)
  415.     {
  416.   case VK_F1:
  417.     if (bShifted && bCtrled) wKey = KCSF1;
  418.     else if (bShifted) wKey = KSF1;
  419.     else if (bCtrled) wKey = KCF1;
  420.     else if (bAlted) wKey = KMF1;
  421.     else wKey = KF1;
  422.     break;
  423.       
  424.   case VK_F2:
  425.     if (bShifted && bCtrled) wKey = KCSF2;
  426.     else if (bShifted) wKey = KSF2;
  427.     else if (bCtrled) wKey = KCF2;
  428.     else if (bAlted) wKey = KMF2;
  429.     else wKey = KF2;
  430.     break;
  431.       
  432.   case VK_F3:
  433.     if (bShifted && bCtrled) wKey = KCSF3;
  434.     else if (bShifted) wKey = KSF3;
  435.     else if (bCtrled) wKey = KCF3;
  436.     else if (bAlted) wKey = KMF3;
  437.     else wKey = KF3;
  438.     break;
  439.       
  440.   case VK_F4:
  441.     if (bShifted && bCtrled) wKey = KCSF4;
  442.     else if (bShifted) wKey = KSF4;
  443.     else if (bCtrled) wKey = KCF4;
  444.     else if (bAlted) wKey = KMF4;
  445.     else wKey = KF4;
  446.     break;
  447.       
  448.   case VK_F5:
  449.     if (bShifted && bCtrled) wKey = KCSF5;
  450.     else if (bShifted) wKey = KSF5;
  451.     else if (bCtrled) wKey = KCF5;
  452.     else if (bAlted) wKey = KMF5;
  453.     else wKey = KF5;
  454.     break;
  455.       
  456.   case VK_F6:
  457.     if (bShifted && bCtrled) wKey = KCSF6;
  458.     else if (bShifted) wKey = KSF6;
  459.     else if (bCtrled) wKey = KCF6;
  460.     else if (bAlted) wKey = KMF6;
  461.     else wKey = KF6;
  462.     break;
  463.       
  464.   case VK_F7:
  465.     if (bShifted && bCtrled) wKey = KCSF7;
  466.     else if (bShifted) wKey = KSF7;
  467.     else if (bCtrled) wKey = KCF7;
  468.     else if (bAlted) wKey = KMF7;
  469.     else wKey = KF7;
  470.     break;
  471.       
  472.   case VK_F8:
  473.     if (bShifted && bCtrled) wKey = KCSF8;
  474.     else if (bShifted) wKey = KSF8;
  475.     else if (bCtrled) wKey = KCF8;
  476.     else if (bAlted) wKey = KMF8;
  477.     else wKey = KF8;
  478.     break;
  479.       
  480.   case VK_F9:
  481.     if (bShifted && bCtrled) wKey = KCSF9;
  482.     else if (bShifted) wKey = KSF9;
  483.     else if (bCtrled) wKey = KCF9;
  484.     else if (bAlted) wKey = KMF9;
  485.     else wKey = KF9;
  486.     break;
  487.   
  488.   case VK_F10:
  489.     if (bShifted && bCtrled) wKey = KCSF10;
  490.     else if (bShifted) wKey = KSF10;
  491.     else if (bCtrled) wKey = KCF10;
  492.     else if (bAlted) wKey = KMF10;
  493.     else wKey = KF10;
  494.     break;
  495.  
  496.   case VK_F11:
  497.     if (bShifted && bCtrled) wKey = KCSF11;
  498.     else if (bShifted) wKey = KSF11;
  499.     else if (bCtrled) wKey = KCF11;
  500.     else if (bAlted) wKey = KMF11;
  501.     else wKey = KF11;
  502.     break;
  503.  
  504.   case VK_F12:
  505.     if (bShifted && bCtrled) wKey = KCSF12;
  506.     else if (bShifted) wKey = KSF12;
  507.     else if (bCtrled) wKey = KCF12;
  508.     else if (bAlted) wKey = KMF12;
  509.     else wKey = KF12;
  510.     break;
  511.  
  512.   default:
  513.     mapped = FALSE;
  514.     }
  515.  
  516.   *pwKey = wKey;
  517.   return (mapped);
  518. }
  519. /* Keypadkey mapping - only partially useful since some
  520. * keys change in value if NUM LOCK is on, which of course
  521. * messes me up big time.
  522. */
  523. static BOOL mapKPkey(WPARAM *pwKey)
  524. {
  525.   WPARAM wKey = *pwKey;
  526.   BOOL mapped = TRUE;
  527.    
  528.   switch(wKey)
  529.     {
  530.   case VK_NUMPAD0:
  531.     wKey = KP0;
  532.     break;
  533.  
  534.   case VK_NUMPAD1:
  535.     wKey = KP1;
  536.     break;
  537.  
  538.   case VK_NUMPAD2:
  539.     wKey = KP2;
  540.     break;
  541.  
  542.   case VK_NUMPAD3:
  543.     wKey = KP3;
  544.     break;
  545.  
  546.   case VK_NUMPAD4:
  547.     wKey = KP4;
  548.     break;
  549.  
  550.   case VK_NUMPAD5:
  551.     wKey = KP5;
  552.     break;
  553.  
  554.   case VK_NUMPAD6:
  555.     wKey = KP6;
  556.     break;
  557.  
  558.   case VK_NUMPAD7:
  559.     wKey = KP7;
  560.     break;
  561.  
  562.   case VK_NUMPAD8:
  563.     wKey = KP8;
  564.     break;
  565.  
  566.   case VK_NUMPAD9:
  567.     wKey = KP9;
  568.     break;
  569.  
  570.   case VK_ADD:
  571.     wKey = KPADD;
  572.     break;
  573.  
  574.   case VK_MULTIPLY:
  575.     wKey = KPMUL;
  576.     break;
  577.  
  578.   case VK_SUBTRACT:
  579.     wKey = KPSUB;
  580.     break;
  581.  
  582.   case VK_DECIMAL:
  583.     wKey = KPDEL;
  584.     break;
  585.  
  586.   case VK_DIVIDE:
  587.     wKey = KPDIV;
  588.     break;
  589.  
  590.   case VK_NUMLOCK:
  591.     wKey = KPNUMLK;
  592.     break;
  593.  
  594.   case VK_EXECUTE:
  595.     wKey = KPENTER;
  596.     break;
  597.  
  598.   default:
  599.     mapped = FALSE;
  600.     }
  601.  
  602.   *pwKey = wKey;
  603.   s_IgnoreWM_CHAR = mapped;    /* generated an event to ignore? */
  604.   return (mapped);
  605. }
  606. #endif
  607.